home *** CD-ROM | disk | FTP | other *** search
- /*
- File: IconDimming.c
-
- Contains: In System 7, selected non-open files are shown as
- dimmed icons on the desktop. This snippet shows
- two different ways to achieve the same results in
- an application.
-
- The first method uses a custom color search
- procedure in place of the current device's to
- create the dimming effect. Once the image has
- been copied to the destination, the custom
- search proc is then removed.
-
- In the second method the RGB components of the
- icon's colortable entries are all dimmed before
- the image is copied into the destination. The
- dimming algorithm used in this method simply
- darkens each RGB component in half then takes
- the two smaller components and darkens them
- in half again. In System 7, this is similar
- to what the Finder does.
-
- Written by: Edgar Lee
-
- Copyright: Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 7/9/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
-
-
- */
- #include<MacTypes.h>
- #include<Quickdraw.h>
- #include<Windows.h>
- #include<Dialogs.h>
- #include<TextEdit.h>
- #include<Fonts.h>
- #include<Menus.h>
- #include<Events.h>
- #include<Resources.h>
-
- /* Constant Declarations */
-
- #define WWIDTH 480
- #define WHEIGHT 180
-
- #define WLEFT (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
- #define WTOP (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
-
- typedef struct
- {
- PixMap pixmap; /* Pixmap used to store the icl8 pixel image. */
- BitMap mask; /* Bitmap used to store the 1 bit mask image of the icl8. */
- }
- MyIconType;
-
- /* Global Variable Definitions */
-
- WindowPtr gWindow;
-
- void initMac();
- void createWindow();
- void loadIconResource();
- void doEventLoop();
-
- void drawIconUnchanged();
- void drawIconUsingSearchProc();
- void drawIconUsingCTable();
-
- void DimColor( RGBColor *aColor );
- long CompareComponents( unsigned short component0, unsigned short component1 );
-
- static pascal Boolean SearchProc();
-
- void main()
- {
- MyIconType icon;
-
- initMac();
-
- createWindow();
- loadIconResource( &icon );
-
- doEventLoop( &icon );
- }
-
- void initMac()
- {
- MaxApplZone();
-
- InitGraf( &qd.thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
- InitCursor();
- FlushEvents( 0, everyEvent );
- }
-
- void createWindow()
- {
- Rect rect;
-
- SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
-
- gWindow = NewCWindow( 0L, &rect, "\pIconDimming", true, noGrowDocProc,
- (WindowPtr)-1L, true, 0L );
- SetPort( gWindow );
-
- TextFont( kFontIDGeneva );
- TextSize( 9 );
- }
-
- void loadIconResource( icon )
- MyIconType *icon;
- {
- Handle icnHandle; /* Handle to the icon bitmap used for the mask. */
- Handle iclHandle; /* Handle to the icl8 resource. */
- char depth; /* Depth of the icl8 image. */
- Rect rect; /* Bounding rect for the image. */
-
- SetRect( &rect, 0, 0, 32, 32 );
- depth = 8;
-
- /* Create the mask. */
-
- icnHandle = GetResource( 'ICN#', 129 );
-
- HLock( icnHandle );
- HNoPurge( icnHandle );
-
- (*icon).mask.baseAddr = *icnHandle + (4 * 32);
- (*icon).mask.rowBytes = 4;
- (*icon).mask.bounds = rect;
-
- /* Create a pixmap for the icl8 pixel image. */
-
- iclHandle = GetResource( 'icl8', 129 );
-
- HLock( iclHandle );
- HNoPurge( iclHandle );
-
- (*icon).pixmap.baseAddr = *iclHandle;
- (*icon).pixmap.rowBytes = ((32 * depth) / 8) | 0x8000;
- (*icon).pixmap.bounds = rect;
- (*icon).pixmap.pmVersion = 0;
- (*icon).pixmap.packType = 0;
- (*icon).pixmap.packSize = 0;
- (*icon).pixmap.hRes = 72;
- (*icon).pixmap.vRes = 72;
- (*icon).pixmap.pixelSize = depth;
- (*icon).pixmap.planeBytes = 0;
- (*icon).pixmap.pmReserved = 0;
- (*icon).pixmap.pixelType = 0;
- (*icon).pixmap.cmpCount = 1;
- (*icon).pixmap.cmpSize = depth;
- (*icon).pixmap.pmTable = GetCTable( depth );
-
- /* Give a unique seed for the pixmap's colortable. Note that this is */
- /* necessary for two reasons. (1) The pixmap's colortable is ignored by */
- /* copybits or copymask if the source ctable's ctseed value matches that */
- /* of the destination's. (2) Matching ctseed values prevent any custom */
- /* searchProcs from being called. */
-
- (**(*icon).pixmap.pmTable).ctSeed = GetCTSeed();
- }
-
- void drawIconUnchanged( icon )
- MyIconType *icon;
- {
- Str255 title = "\pOriginal 'icl8'";
- Rect rect;
-
- /* Draw the original icl8 image unchanged. */
-
- SetRect( &rect, 0, 0, 160, 160 );
- CopyMask( (BitMap *)&(*icon).pixmap, &(*icon).mask, &gWindow->portBits,
- &(*icon).pixmap.bounds, &(*icon).mask.bounds, &rect );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- void drawIconUsingSearchProc( icon )
- MyIconType *icon;
- {
- Str255 title = "\p'icl8' using SearchProc Dimming";
- Rect rect;
- GWorldPtr gworld; /* Offscreen used for the custom search procedure. */
- CGrafPtr currentPort; /* Saved CGrafPort for later restore. */
- GDHandle currentDevice; /* Saved gdDevice for later restore. */
-
- GetGWorld( ¤tPort, ¤tDevice );
-
- /* Install the custom search proc to an offscreen pixmap instead of the */
- /* screen's in order to be courteous to other apps. */
-
- NewGWorld( &gworld, 8, &(*icon).pixmap.bounds, GetCTable( 8 ), nil, 0 );
- HLock( (Handle)(*gworld).portPixMap );
-
- SetGWorld( gworld, nil );
- AddSearch( NewColorSearchProc(SearchProc) );
-
- CopyBits( (BitMapPtr)&(*icon).pixmap, (BitMapPtr)&(*gworld).portPixMap, &(*icon).pixmap.bounds,
- &(**(*gworld).portPixMap).bounds, srcCopy, nil );
-
- DelSearch( NewColorSearchProc(SearchProc) );
- SetGWorld( currentPort, currentDevice );
-
- /* Now copy the dimmed pixmap image to the window. */
-
- rect.left = (*icon).pixmap.bounds.right * 5;
- rect.top = (*icon).pixmap.bounds.top;
- rect.right = (*icon).pixmap.bounds.right * 5 + rect.left;
- rect.bottom = (*icon).pixmap.bounds.bottom * 5;
-
- CopyMask( (BitMapPtr)(*(*gworld).portPixMap), &(*icon).mask, &gWindow->portBits,
- &(**(*gworld).portPixMap).bounds, &(*icon).mask.bounds, &rect );
-
- DisposeGWorld( gworld );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- static pascal Boolean SearchProc( color, position )
- RGBColor *color;
- long *position;
- {
- #pragma unused(position)
- /* Darken the RGB components in half. Note that this routine could just */
- /* have easily called DimColor; however, I wanted to show the difference */
- /* between just dimming the components in half to what System 7 does. */
-
- color->red >>= 1;
- color->green >>= 1;
- color->blue >>= 1;
-
- return false;
- }
-
- void drawIconUsingCTable( icon )
- MyIconType *icon;
- {
- Str255 title = "\p'icl8' using Colortable Dimming";
- Rect rect;
- short index; /* Index into the dimmed colortable */
- CTabHandle dimmedClut; /* Holds dimmed version of icon’s colortable */
- CTabHandle savedClut; /* Saves the icon’s original colortable */
-
- /* Save the icon’s color table and make a copy of it */
- dimmedClut = savedClut = (*icon).pixmap.pmTable;
- HandToHand( &(Handle)dimmedClut );
-
- /* Dim each of the colors in the copy of the color table */
- for (index = 0; index <= (**dimmedClut).ctSize; ++index)
- DimColor( &(**dimmedClut).ctTable[index].rgb );
-
- /* Install the dimmed copy of the color table */
- (*icon).pixmap.pmTable = dimmedClut;
-
- rect.left = (*icon).pixmap.bounds.right * 10;
- rect.top = (*icon).pixmap.bounds.top;
- rect.right = (*icon).pixmap.bounds.right * 5 + rect.left;
- rect.bottom = (*icon).pixmap.bounds.bottom * 5;
-
- /* Now copy the dimmed pixmap image to the window. */
-
- CopyMask( (BitMap *)&(*icon).pixmap, &(*icon).mask, &gWindow->portBits,
- &(*icon).pixmap.bounds, &(*icon).mask.bounds, &rect );
-
- (*icon).pixmap.pmTable = savedClut;
- DisposeCTable( dimmedClut );
-
- MoveTo( (rect.right - rect.left - StringWidth( title )) / 2 + rect.left,
- rect.bottom + 15 );
- DrawString( title );
- }
-
- /******************************************************************************\
- * DimColor - Dim one color for selection
- * written by Forrest Tanaka
- * This routine dims the color that’s passed in the aColor parameter so that
- * it’s suitable to use for making an icon look selected. It works by dimming
- * all components by half, and then dimming the smaller two components by half
- * again. By keeping the largest component dimmed by only half, we keep the
- * saturation of the color approximately what it was before it was dimmed.
- \******************************************************************************/
-
- void DimColor(
- RGBColor *aColor)
- {
- unsigned short *biggest; /* Pointer to the biggest component */
-
- /* Dim all components by half */
- aColor->red >>= 1;
- aColor->green >>= 1;
- aColor->blue >>= 1;
-
- /* If aColor isn’t nearly gray, dim smallest 2 components again by half */
- if (CompareComponents( aColor->red, aColor->green ) != 0 ||
- CompareComponents( aColor->red, aColor->blue ) != 0)
- {
- /* Point to the larger of red and green */
- if (CompareComponents( aColor->red, aColor->green ) > 0)
- biggest = &aColor->red;
- else
- biggest = &aColor->green;
-
- /* Point to the larger of previous test and blue */
- if (CompareComponents( aColor->blue, *biggest ) > 0)
- biggest = &aColor->blue;
-
- /* Dim smaller two components by half */
- if (&aColor->red != biggest)
- aColor->red >>= 1;
- if (&aColor->green != biggest)
- aColor->green >>= 1;
- if (&aColor->blue != biggest)
- aColor->blue >>= 1;
- }
- }
-
- /******************************************************************************\
- * CompareComponents - Compare two components for difference and equality
- * written by Forrest Tanaka
- * This routine compares two components of an RGBColor that are passed in the
- * component0 and component1 parameters. If they’re within 512 units of each
- * other, then zero is returned. Otherwise, the positive difference is returned
- * if component0 is greater than component1, or the negative of the difference
- * is returned if component1 is greater than component0.
- \******************************************************************************/
-
- long CompareComponents(
- unsigned short component0, /* First component to check */
- unsigned short component1) /* Second component to check */
- {
- long difference; /* Difference between components */
-
- /* Calculate the difference between the components */
- difference = (unsigned long)component0 - (unsigned long)component1;
-
- /* If the difference is within 512 units, then consider the components the same */
- if ((difference < 512) && (difference > -512))
- return 0;
- else
- return difference;
- }
-
- void doEventLoop( icon )
- MyIconType *icon;
- {
- EventRecord event;
- WindowPtr window;
- short clickArea;
- Rect screenRect;
-
- for (;;)
- {
- if (WaitNextEvent( everyEvent, &event, 0, nil ))
- {
- if (event.what == mouseDown)
- {
- clickArea = FindWindow( event.where, &window );
-
- if (clickArea == inDrag)
- {
- screenRect = (**GetGrayRgn()).rgnBBox;
- DragWindow( window, event.where, &screenRect );
- }
- else if (clickArea == inContent)
- {
- if (window != FrontWindow())
- SelectWindow( window );
- }
- else if (clickArea == inGoAway)
- if (TrackGoAway( window, event.where ))
- return;
- }
- else if (event.what == updateEvt)
- {
- window = (WindowPtr)event.message;
- SetPort( window );
-
- BeginUpdate( window );
-
- drawIconUnchanged( icon );
- drawIconUsingSearchProc( icon );
- drawIconUsingCTable( icon );
-
- EndUpdate( window );
- }
- }
- }
- }